﻿
#region itdc
/**
 * 该脚本是发射物的基类。
 * 子类需要实现抽象方法Move(T t)移动方式。可以是刚体的速度移动，也可以是按照时间匀速移动
 * **/
#endregion


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

    public enum Shot
    {
        RAY,ENEMY_RAY,Sniper_gun
    }
/// <summary>
/// 发射物基类。需要触发器检测命中
/// </summary>
[RequireComponent(typeof(Collider))]
public abstract class Shots : MonoBehaviour
{
    #region field
    [SerializeField, Tooltip("伤害值。包含伤害类型和伤害值默认1，激光伤害")]
    protected Damage shotDamage = new Damage(1, null, DamageType.XRAY);
    protected Collider co;//检测命中目标
    [SerializeField, Tooltip("持续时间")]
    protected float dueTime = 5f;
    [SerializeField, Tooltip("爆炸显示的粒子")]
    protected GameObject explode;
    #endregion
    //private static GameObject[] shots;//静态存储所有shots物体，方便获取


    #region constField
    //  private GameObject shots ;
    // shots = Resources.Load("Prefabs/EventObject/Triggers/Particles/Laser") as GameObject;
    //各个子类物体在资源管理shots数组中的下标
    public const int RAY = 0;
    public const int ENEMY_RAY = 1;
    #endregion

    public Damage ShotDamage
    {
        get
        {
            return shotDamage;
        }

        set
        {
            shotDamage = value;
        }
    }


    #region normalMethod
    /// <summary>
    /// 目中目标时的逻辑.子类可以重写
    /// </summary>
    protected virtual void OnTriggerEnter(Collider other)
    {
        string tag = other.tag;
       // print(tag);
        if (tag=="Entity"||tag=="Player")//如果是实体，包括玩家
        {
            OnEntityHit(other);
         
        }
        else if (tag == "ColliderObj")
        {
            SelfDestroy();//撞墙直接爆炸开
        }
        else if (tag == "TriggerObj")
        {
            OnTriggerHit(other);
        }
        else
        {
            SelfDestroy();//直接爆炸开
        }


    }
    #region virtual method

    /// <summary>
    /// 命中entity时的逻辑
    /// </summary>
    /// <param name="e"></param>
    protected virtual void OnEntityHit(Collider e)
    {
        IVictim vct = e.GetComponent<IVictim>();
        this.ProbeIsNull(vct, false, name + "don't find victim");
        shotDamage.Victim = vct;//确定目标，处理伤害
        SelfDestroy();
    }

    /// <summary>
    /// 命中trigger时的逻辑
    /// </summary>
    /// <param name="e"></param>
    protected virtual void OnTriggerHit(Collider e)
    {
        //write me
        if (e.name.Contains("Gate"))
        {
            SelfDestroy();
        }
    }

    #endregion

    /// <summary>
    /// 命中目标后的爆炸效果及销毁自身.若改名字，注意下面的Invoke函数
    /// </summary>
    protected virtual void SelfDestroy()
    {
        if (explode != null)
        {
            Explode(transform.position+new Vector3(0,0,-65));
        }
        GameObject.Destroy(gameObject);
    }

    /// <summary>
    /// 持续一段时间自动销毁
    /// </summary>
    private void Awake()
    {
       
        Invoke("SelfDestroy", dueTime);
       
    }

    /// <summary>
    /// 在指定位置创建爆炸物。
    /// </summary>
    protected virtual void Explode(Vector3 pos)
    {
        GameObject.Instantiate(explode, pos, Quaternion.identity);
    }
    #endregion


    #region interface

    /// <summary>
    /// 供外部使用的发射物体静态方法。返回shots脚本，可以改动伤害值
    /// </summary>
    /// <typeparam name="TM"></typeparam>
    /// <param name="tm"></param>
    /// <param name="startPos"></param>
    /// <param name="type"></param>
    public static Shots Shot(Vector3 startVelocity, Vector3 startPos, int type, Quaternion qua)
    {

        GameObject shot = GameObject.Instantiate(ResourceManager.Instance.shots[type].GmObj, startPos, qua);
        Shots result = shot.GetComponent<Shots>();
        result.Move(startVelocity);
        Helper.ProbeIsNull(GameManager.Instance, result, true, "shots building error,can't find shots component");
        return result;
    }



    #region 重载

    public static Shots Shot(Vector3 startVelocity, Vector3 startPos, int type) { return Shot(startVelocity, startPos, type, Quaternion.identity); }

    public static Shots Shot(Vector3 startVelocity, Vector3 startPos, int type, Damage damage, Quaternion qua)
    {
        Shots s = Shot(startVelocity, startPos, type, qua);
        s.shotDamage = damage;
        return s;
    }

    public static Shots Shot(Vector3 startVelocity, Vector3 startPos, int type, Damage damage)
    {
        Shots s = Shot(startVelocity, startPos, type);
        s.shotDamage = damage;
        return s;
    }

    /// <summary>
    /// 发射枪长，速度，起点，目标
    /// </summary>
    /// <param name="distance_Gun"></param>
    /// <param name="v"></param>
    /// <param name="start"></param>
    /// <param name="tagert"></param>
    /// <returns></returns>
    public static Damage Shot(float distance_Gun, float v, Vector3 start, Vector3 tagert)
    {
        Vector3 charp = tagert - start;
        Vector3 shotVelocity = charp.normalized * v;
        Vector3 startPos = start + distance_Gun * charp.normalized;
        return Shots.Shot(shotVelocity, startPos, Shots.RAY).ShotDamage;
    }

    /// <summary>
    /// 在某个物体坐标位置的四个方向之一发射一个shot
    /// </summary>
    /// <param name="shoter"></param>
    /// <param name="dir"></param>
    /// <param name="distance_Gun"></param>
    /// <param name="shotDamage"></param>
    public static void Shot(Vector3 shoter, Direction dir, float distance_Gun, Damage shotDamage)
    {
        Vector3 shotV = MoveControl.eEect[(int)dir]; ;
        Vector3 startPos = shoter + distance_Gun * MoveControl.eEect[(int)dir];
        Helper.DebugPrint(startPos);
        Shots.Shot(shotV, startPos, Shots.RAY, shotDamage);
    }

    public static void Shot(Vector3 shoter,Vector3 tagert,float distance_Gun,Damage shotDamage)
    {

    }


    #endregion


    #endregion




    #region abstractMethod


    /// <summary>
    /// 发射后的移动方式
    /// 传入初始状态
    /// </summary>
    /// <param name="startVelocity">初始状态</param>
    protected abstract void Move(Vector3 startStatu);


    #endregion

}


